package com.myrslok.set;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.HashSet;
import java.util.Set;

public abstract class BasicArchive {

    private static final Logger logger = LoggerFactory.getLogger(BasicArchive.class);

    @NotNull
    final File target;
    @NotNull
    private final ResourceSet<FileToFileResource> set = new ResourceSet<FileToFileResource>();
    @Nullable
    private final File baseDir;

    BasicArchive(@NotNull final File target, @Nullable final File baseDir) {
        this.baseDir = baseDir;
        this.target = target;
    }

    public Set<FileToFileResource> getResources() {
        final Set<FileToFileResource> resources = new HashSet<FileToFileResource>();
        resources.addAll(set.getResources());
        if (baseDir != null) {
            if (!baseDir.exists()) {
                logger.warn(baseDir + " does not exist (absolute path: " + baseDir.getAbsolutePath() + ")");
            } else if (!baseDir.isDirectory()) {
                logger.warn(baseDir + " is not a directory (absolute path: " + baseDir.getAbsolutePath() + ")");
            } else {
                resources.addAll(getResourcesRecursive(baseDir, null));
            }
        }
        return resources;
    }

    private Set<FileToFileResource> getResourcesRecursive(@NotNull final File dir, @Nullable final File targetBase) {
        final Set<FileToFileResource> resources = new HashSet<FileToFileResource>();
        for (@NotNull final File sourceFile : dir.listFiles()) {
            final File targetFile = new File(targetBase, sourceFile.getName());
            if (sourceFile.isFile()) {
                resources.add(new FileToFileResource(sourceFile, targetFile));
            } else if (sourceFile.isDirectory()) {
                resources.addAll(getResourcesRecursive(sourceFile, targetFile));
            }
        }
        return resources;
    }

    public abstract void archive();

    public abstract void extractTo(@NotNull File dest);

    public void extractTo(@NotNull final String dest) {
        extractTo(new File(dest));
    }

    public void extractToLocation() {
        final File parentFile = target.getParentFile();
        if (parentFile != null) {
            extractTo(parentFile);
        } else {
            extractTo(".");
        }
    }
    
}
